﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using TechMadeira.Data.Classes;

namespace TechMadeira.Data
{
    public partial class Repository : IFactory
    {
        #region Singleton usage: Repository.Instance
        private static readonly Repository mInstance = new Repository();

        static Repository()
        {
        }

        private Repository()
        {
        }

        public static Repository Instance { get { return mInstance; } }

        #endregion

        public IFactory Factory { get; set; }

        public Type[] GetTypes()
        {
            if ( Factory == null ) return null;
            return Factory.GetTypes();
        }

        public object CreateObject( string aType )
        {
            if ( Factory == null ) return null;

            var semantic = (ISemantic) Factory.CreateObject( aType );
            mData.Append( semantic );
            return semantic;
        }

        public T CreateObject<T>()
        {
            if ( Factory == null ) return default(T);

            var semantic = Factory.CreateObject<T>();
            mData.Append( (ISemantic) semantic );
            return semantic;
        }

        public void Append( ISemantic aSemantic )
        {
            mData.Append( aSemantic );
        }

        public void Remove( ISemantic aSemantic )
        {
            mData.Remove( aSemantic );
        }

        public IEnumerable<T> Select< T >()
        {
            IList<T> result = new List<T>();
            foreach ( var semantic in mData.Semantics )
            {
                if ( ! ( semantic is T ) ) continue;
                result.Add( (T) semantic );
            }
            return result;
        }

        public delegate bool Predicate< T >( T arg );

        public IEnumerable<T> Select< T >( Predicate<T> aPredicate )
        {
            IList<T> result = new List<T>();
            foreach ( var semantic in mData.Semantics )
            {
                if ( ! ( semantic is T ) ) continue;
                if ( ! aPredicate( (T) semantic ) ) continue;
                result.Add( (T) semantic );
            }
            return result;
        }
    }
}
